package templateExecel2.extract;

import templateExecel2.utils.StringUtils;

import java.lang.reflect.Field;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

//提取单元格提取器
public class ExtractCellCompiler {


    private static Pattern PATTERN = Pattern.compile("@\\{(?<name>[a-z][a-z0-9]*(\\[[a-z0-9]*])?(\\.[a-z][a-z0-9]*)*(\\[[a-z0-9]*])?)}");

    /*
        转换目标
        1. 将${xxx}转换为(?<xxx>.*)的形式
     */

    public static RegexExtractCell compile(String exp) {

        RegexExtractCell extractCell = new RegexExtractCell();

        exp = handleHolder(exp);

        Set<String> groups = new HashSet<>();

        exp = handleGroup(exp, groups);

        //编译
        Pattern compile = Pattern.compile(exp);

        extractCell.setMatchPattern(compile);

        //所有变量
        extractCell.setVariables(namedGroups(compile));

        extractCell.setTransmutativeGroups(groups);

        return extractCell;

    }

    private static Field field;

    static {
        Class<Pattern> clazz = Pattern.class;

        try {
            field = clazz.getDeclaredField("namedGroups");
            field.setAccessible(true);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

    }

    private static Set<String> namedGroups(Pattern pattern) {
        try {
            Map<String, Integer> o = (Map<String, Integer>) field.get(pattern);
            if (o == null) {
                return null;
            }
            return o.keySet();
        } catch (IllegalAccessException e) {
            return null;
        }
    }


    //表达式
    private static Pattern HOLDER_PATTERN = Pattern.compile("\\$\\{");

    private static String handleHolder(String s) {

        Matcher matcher = HOLDER_PATTERN.matcher(s);
        int end = 0;
        StringBuilder builder = new StringBuilder();

        while (matcher.find()) {

            //放入字符串的转译
            builder.append(translation(s.substring(end, matcher.start())));

            end = matcher.end();

            //查找大括号
            StringUtils.SubStringResult exp = StringUtils.pairingSubString(s, end - 1, '{', '}');

            if (exp != null && exp.startEqualsFrom()) {

                //查找名称表达式
                StringUtils.SubStringResult n = StringUtils.findCharSubString(s, end, '/');

                if (n != null) {
                    String name = null;
                    String regex = null;
                    if (n.getEnd() < exp.getEnd()) {//存在正则
                        if (n.empty()) {//没有名称只有正则
                            regex = exp.getSubString().trim();
                            regex = regex.substring(1, regex.length() - 1);
                            if (regex.length() == 0) {
                                regex = null;
                            }
                        } else {
                            //分为名称子正则两部分
                            name = n.getSubString().trim();
                            if (name.length() == 0) {
                                name = null;
                            }
                            regex = s.substring(n.getEnd(), exp.getEnd() - 1).trim();
                            regex = regex.substring(1, regex.length() - 1);
                            if (regex.length() == 0) {
                                regex = null;
                            }
                        }
                    } else {
                        //获取名称
                        name = exp.getSubString();
                        name = name.substring(1, name.length() - 1).trim();
                        if (name.length() == 0) {
                            name = null;
                        }
                    }

                    String st = null;

                    if (name == null) {

                        //如果存在正则
                        if (regex != null) {
                            st = regex;
                        }

                    } else {

                        //去除掉所有的空格
                        name = name.replace(" ", "");

                        if (regex == null) {
                            regex = ".*";
                        }

                        //提取
                        st = "(?<" + name + ">" + regex + ")";

                    }

                    if (st != null) {
                        builder.append(st);
                    }

                }

                end = exp.getEnd();

            }

        }

        if (end < s.length() - 1) {
            builder.append(translation(s.substring(end)));
        }

        return builder.toString();
    }

    private static Pattern GROUP_PATTERN = Pattern.compile("\\(\\?<([a-z0-9.\\[\\]]+)>");


    //处理分组
    private static String handleGroup(String s, Set<String> list) {

        Matcher matcher = GROUP_PATTERN.matcher(s);
        int end = 0;
        StringBuilder builder = new StringBuilder();

        while (matcher.find()) {

            builder.append(s, end, matcher.start());
            end = matcher.end();

            String o = matcher.group(1);

            String r = o.replace(".", "0POINT0").replace("[", "0BRACKET0PRE0").replace("]", "0BRACKET0POST0");

            builder.append("(?<").append(r).append(">");

            //放入list
            if (o.length() != r.length()) {
                list.add(r);
            }

        }

        if (end < s.length() - 1) {
            builder.append(s.substring(end));
        }
        return builder.toString();
    }

    private static String translation(String s) {
        return s.replaceAll("([$\\[\\]{}*+.?\\\\^()|'\"])", "\\\\$1");
    }


}
